use std::net::Ipv4Addr;
use std::str::FromStr;
use std::time::Instant;

fn main() {
    // 获取命令行参数
    let args: Vec<String> = std::env::args().collect();

    // 检查参数数量
    if args.len() != 3 {
        eprintln!("用法: {} <IP地址> <通配符掩码>", args[0]);
        eprintln!("示例: {} 192.168.1.1 0.0.0.3", args[0]);
        std::process::exit(1);
    }

    // 解析 IP 地址
    let ip = match Ipv4Addr::from_str(&args[1]) {
        Ok(ip) => ip,
        Err(e) => {
            eprintln!("无效的 IP 地址: {}", e);
            std::process::exit(1);
        }
    };

    // 解析通配符掩码
    let wildcard_mask = match Ipv4Addr::from_str(&args[2]) {
        Ok(mask) => mask,
        Err(e) => {
            eprintln!("无效的通配符掩码: {}", e);
            std::process::exit(1);
        }
    };

    let started = Instant::now();
    // 计算所有匹配的 IP 地址
    let matching_ips = calculate_matching_ips(ip, wildcard_mask);
    let use_time = format!("{:.2?}", started.elapsed());

    // 输出结果
    println!("与 {} 匹配（通配符掩码：{}）的 IP 地址清单：", args[1], args[2]);
    for ip in &matching_ips {
        println!("{}", ip);
    }
    println!("共匹配 {} 个 IP 地址，耗时{}", matching_ips.len(), use_time);
}

/// 计算与给定 IP 地址和通配符掩码匹配的所有 IP 地址
fn calculate_matching_ips(ip: Ipv4Addr, wildcard_mask: Ipv4Addr) -> Vec<Ipv4Addr> {
    // 将 IP 和通配符掩码转换为 32 位整数
    let ip_int = ip_to_u32(ip);
    let mask_int = ip_to_u32(wildcard_mask);

    // 计算固定位和可变位
    // 固定位：通配符掩码中为 0 的位，必须精确匹配
    // 可变位：通配符掩码中为 1 的位，可以是 0 或 1
    let fixed_bits = ip_int & !mask_int;
    let variable_mask = mask_int;

    // 计算可变位的数量
    let variable_bits_count = variable_mask.count_ones() as usize;

    // 检查可变位数量，避免生成过多 IP 地址导致性能问题
    if variable_bits_count > 20 {
        eprintln!("错误：通配符掩码包含太多可变位（{}位），可能会生成超过一百万的 IP 地址，这可能导致性能问题。", variable_bits_count);
        std::process::exit(1);
    }

    // 计算可能的 IP 地址数量 (2^variable_bits_count)
    let total_ips = 1u32 << variable_bits_count;
    println!("将生成 {} 个匹配的 IP 地址...", total_ips);

    // 生成所有可能的 IP 地址
    let mut matching_ips = Vec::with_capacity(total_ips as usize);
    for i in 0..total_ips {
        // 将 i 的位填充到可变位的位置
        let mut ip = fixed_bits;
        let mut temp_i = i;

        // 遍历每个位，将 temp_i 的位填充到可变位
        for bit in 0..32 {
            if (variable_mask >> bit) & 1 != 0 {
                ip |= (temp_i & 1) << bit;
                temp_i >>= 1;
            }
        }

        matching_ips.push(u32_to_ip(ip));
    }

    matching_ips
}

/// 将 Ipv4Addr 转换为 32 位整数
fn ip_to_u32(ip: Ipv4Addr) -> u32 {
    let octets = ip.octets();
    ((octets[0] as u32) << 24) |
        ((octets[1] as u32) << 16) |
        ((octets[2] as u32) << 8) |
        (octets[3] as u32)
}

/// 将 32 位整数转换为 Ipv4Addr
fn u32_to_ip(n: u32) -> Ipv4Addr {
    Ipv4Addr::new(
        ((n >> 24) & 0xFF) as u8,
        ((n >> 16) & 0xFF) as u8,
        ((n >> 8) & 0xFF) as u8,
        (n & 0xFF) as u8,
    )
}
